//  
//  Sprawdzacz
//  
//  Author:
//       Grzegorz Żur <grzegorz.zur@gmail.com>
// 
//  Copyright (c) 2010-2011 Grzegorz Żur
// 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

using System;
using System.Text.RegularExpressions;

namespace Sprawdzacz
{

	public class REGON : Validator
	{

		public const string NAME = "REGON";

		private static readonly Regex PATTERN = new Regex ("^[0-9]{7}|[0-9]{9}|[0-9]{14}$");

		private const int DIVIDER_1 = 11;

		private const int DIVIDER_2 = 10;

		private const int CHECKSUM_POSITION_9 = 8;

		private const int CHECKSUM_POSITION_14 = 13;

		private static readonly int[] WEIGHTS_9 = { 8, 9, 2, 3, 4, 5, 6, 7, 0 };

		private static readonly int[] WEIGHTS_14 = { 2, 4, 8, 5, 0, 9, 7, 3, 6, 1, 2, 4, 8, 0 };

		public REGON () : base(NAME)
		{
		}

		public override Validation Validate (string number)
		{
			number = Normalize (number);
			if (!PATTERN.IsMatch (number))
				return new Validation (false, Name, number, null);
			
			switch (number.Length) {
			case 7:
				return Validate7 (number);
			case 9:
				return Validate9 (number);
			case 14:
				return Validate14 (number);
			default:
				return new Validation (false, Name, number, null);
			}
		}

		private Validation Validate7 (string number)
		{
			return Validate9 ("00" + number);
		}

		private Validation Validate9 (string number)
		{
			int[] digits = Numbers (number);
			int checksum = digits[CHECKSUM_POSITION_9];
			int sum = Sum (WEIGHTS_9, digits);
			int reminder = sum % DIVIDER_1 % DIVIDER_2;
			if (reminder != checksum)
				return new Validation (false, Name, number, null);
			
			string message = string.Format ("{0}-{1}-{2}", number.Substring (0, 3), number.Substring (3, 3), number.Substring (6, 3));
			return new Validation (true, Name, number, message);
		}

		private Validation Validate14 (string number)
		{
			Validation validation9 = Validate9 (number.Substring (0, 9));
			if (!validation9.Correct)
				return new Validation (false, Name, number, null);
			
			int[] digits = Numbers (number);
			int checksum = digits[CHECKSUM_POSITION_14];
			int sum = Sum (WEIGHTS_14, digits);
			int reminder = sum % DIVIDER_1 % DIVIDER_2;
			if (reminder != checksum)
				return new Validation (false, Name, number, null);
			
			string message = string.Format ("{0}-{1}-{2}-{3}-{4}", number.Substring (0, 2), number.Substring (2, 3), number.Substring (5, 3), number.Substring (8, 3), number.Substring (11, 3));
			return new Validation (true, Name, number, message);
		}
		
	}
	
}
